package com.example.sys.service;

import com.example.common.exception.BizException;
import com.example.common.exception.errcode.ErrCodeLogin;
import com.example.common.utils.BeanUtils;
import com.example.common.utils.DateUtils;
import com.example.common.utils.JwtUtils;
import com.example.sys.dao.SysUserRepository;
import com.example.sys.dao.SysUserRoleDao;
import com.example.sys.entity.dto.LoginUserDto;
import com.example.sys.entity.po.SysRole;
import com.example.sys.entity.po.SysUser;
import com.example.sys.entity.vo.LoginUserInfoVo;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class LoginService {
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private SysUserRepository sysUserRepository;
    @Resource
    private SysUserRoleDao sysUserRoleDao;

    public LoginUserInfoVo loginByIphoneNoAndPwd(LoginUserDto loginUserDto) {
        SysUser sysUser = sysUserRepository.findByIphoneNo(loginUserDto.getIphoneNo()); //根据手机号查询用户
        return packLoginUserInfo(sysUser, loginUserDto);
    }

    public LoginUserInfoVo loginByEmailAndPwd(LoginUserDto loginUserDto) {
        SysUser sysUser = sysUserRepository.findByEmailAddress(loginUserDto.getEmailAddress()); //根据邮箱查询用户信息
        return packLoginUserInfo(sysUser, loginUserDto);
    }

    /**
     * 统一操作逻辑
     * 1,校验用户是否存在
     * 2,用户存在密码是否正确
     * 密码正确,把基本的信息返回,并生成 token 返回
     *
     * @param sysUser
     * @return
     */
    private LoginUserInfoVo packLoginUserInfo(SysUser sysUser, LoginUserDto loginUserDto) {
        if (sysUser == null) {
            throw new BizException(ErrCodeLogin.ACCOUNT_NOT_REGISTERED_ERROR);  //账号未注册
        }
        boolean matches = passwordEncoder.matches(loginUserDto.getUserPwd(), sysUser.getUserPwd());//校验密码
        if (!matches) {
            throw new BizException(ErrCodeLogin.ACCOUNT_OR_PASSWORD_ERROR_EXCEPTION);  //账号或密码错误
        }
        //用户角色列表信息
        List<SysRole> sysRoleList = sysUserRoleDao.selectSysRoleListByUserId(sysUser.getUserId());
        //生成 token
        LoginUserInfoVo.Token token = LoginUserInfoVo.Token.builder()
                .accessToken(JwtUtils.generateAccessToken(JwtUtils.JwtUser.builder()
                                .id(sysUser.getUserId().toString())
                                .subject(sysUser.getUserName())
                                .issuer("Demo系统")
                                .audience("普通用户")
                                .expiration(DateUtils.operationTime(new Date(),2,0,0))//todo过期时间可以设置成一个月后
                                .notBefore(new Date())    //在此之前不可用
                                .lastLoginTime(new Date())//上次登录时间
                                .roleList(BeanUtils.facade().mapAsList(sysRoleList, JwtUtils.RoleInfo.class))
                        .build()))
                .refreshToken("刷新令牌" + UUID.randomUUID().toString().replace("-", ""))//todo
                .build();
        LoginUserInfoVo loginUserInfoVo = LoginUserInfoVo.builder()
                .userId(sysUser.getUserId())
                .userInfo(BeanUtils.facade().map(sysUser, LoginUserInfoVo.UserInfo.class))
                .roleList(BeanUtils.facade().mapAsList(sysRoleList, LoginUserInfoVo.RoleInfo.class))
                .token(token)
                .build();
        return loginUserInfoVo;
    }
}
